﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;

namespace CSConsoleTest
{
    class TestReflection : BaseConsoleTest
    {
        public void printDescription()
        {
            Console.WriteLine("--- Reflection ---");
        }

        public void doTest()
        {
            //Reflection Basic
            int reflectionVal = 5;
            Type type1 = reflectionVal.GetType();
            Type type2 = typeof(int);
            Type type3 = Type.GetType("System.Int32");
            Type calcType1 = typeof(ReflectionCalculater);
            Object calcObj1 = Activator.CreateInstance(calcType1);
            PropertyInfo userMsgProp = calcType1.GetProperty("UserMessage");
            userMsgProp.SetValue(calcObj1, "This is Plus operation.");
            MethodInfo plusMethod = calcType1.GetMethod("plus");
            plusMethod.Invoke(calcObj1, new object[]{3, 5});

            //Reflection : Type Export
            AssemblyBuilder calcAssemblyBuilder
                = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("ReflectionCalcAssembly"), AssemblyBuilderAccess.Run);
            ModuleBuilder calcModuleBuilder = calcAssemblyBuilder.DefineDynamicModule("ReflectionCalcModule");
            TypeBuilder calcTypeBuilder = calcModuleBuilder.DefineType("ReflectionCalcType");
            MethodBuilder minusMethodBuilder = calcTypeBuilder.DefineMethod("minus", MethodAttributes.Public, typeof(int), new Type[] { typeof(int), typeof(int) });
            ILGenerator minusMethodILGenerator = minusMethodBuilder.GetILGenerator();
            minusMethodILGenerator.Emit(OpCodes.Ldarg_1);
            minusMethodILGenerator.Emit(OpCodes.Ldarg_2);
            minusMethodILGenerator.Emit(OpCodes.Sub);
            minusMethodILGenerator.Emit(OpCodes.Ret);

            Type calcType2 = calcTypeBuilder.CreateType();
            object calcObj2= Activator.CreateInstance(calcType2);
            MethodInfo minusMethod = calcType2.GetMethod("minus");

            int plusResult = (int)minusMethod.Invoke(calcObj2, new object[2] { 3, 5 });
            Console.WriteLine("{0} - {1} = {2}", 3, 5, plusResult);
        }
    }

    class ReflectionCalculater
    {
        public string UserMessage
        {
            get;
            set;
        }

        public void plus(int aArg1, int aArg2)
        {
            Console.WriteLine("Msg : {0} : {1} + {2} = {3}", UserMessage, aArg1, aArg2, aArg1 + aArg2);
        }

    }
}
